package net.bat.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Vector;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.bat.db.BaseDAOImpl;
import net.bat.util.Cfg;
import net.cs.um.UMService;

import org.jabsorb.JSONSerializer;
import org.jabsorb.serializer.MarshallException;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import dao.hb.NSort;
import dao.hb.UOrg;
import dao.hb.UUser;

class Node{
	int id;
	String text;
	boolean leaf;
	Node[] children=null;
	boolean checked = false;
	
	ArrayList<Node> clist=new ArrayList<Node>();
	Node(int id,String text){
		this.id=id;
		this.text = text;
	}
	void addNode(Node nd){
		clist.add(nd);
	}
	void update(){
		int len =clist.size();
		if(len==0){
			leaf = true;
		}else{
			//TODO 按ord排序
			leaf=false;
			children = new Node[len];
			for(int i=0; i<len; i++){
				Node cn = clist.get(i);
				cn.update();
				children[i]=cn;
			}
		}
	}
	Node[] getChildren(){
		return children;
	}
}

class NodeSingle{
	int id;
	String text;
	boolean leaf;
	NodeSingle[] children=null;
	Object value;
	
	ArrayList<NodeSingle> clist=new ArrayList<NodeSingle>();
	NodeSingle(int id,String text){
		this.id=id;
		this.text = text;
	}
	NodeSingle(int id,String text,Object val){
		this.id=id;
		this.text = text;
		this.value = val;
	}
	void addNode(NodeSingle nd){
		clist.add(nd);
	}
	void update(){
		int len =clist.size();
		if(len==0){
			leaf = true;
		}else{
			//TODO 按ord排序
			leaf=false;
			children = new NodeSingle[len];
			for(int i=0; i<len; i++){
				NodeSingle cn = clist.get(i);
				cn.update();
				children[i]=cn;
			}
		}
	}
	NodeSingle[] getChildren(){
		return children;
	}
}

public class JSonBaseServlet extends HttpServlet {
	/**
	 * 
	 */
	static public String SPLIT_LANG_COUNTRY = "-";
	private static final long serialVersionUID = 1L;
	private BaseDAOImpl dao=null;
	//static private JSONSerializer ser;
	static Gson gson=new GsonBuilder().setPrettyPrinting().create();
	
	private HashMap<String,String> ls_map;

	public BaseDAOImpl getDao() {
		if(dao==null) {
			dao = (BaseDAOImpl)Cfg.getBean("BaseDAOImpl");
		}
		return dao;
	}
	public void setDao(BaseDAOImpl dao) {
		this.dao = dao;
	} 	 
    @Override
	public void init() throws ServletException {
    	ls_map = new HashMap<String,String>();
    }
    
    public void putJSon(String hql,String jsonStr){
    	ls_map.put(hql, jsonStr);
    }
    public String getJSon(String hql){
    	return ls_map.get(hql);
    }
    private List<String[]> listLang(String lang){
		Vector<String[]> rl = new Vector<String[]>();
		Locale[] localeList = Locale.getAvailableLocales();
		String[] lc = lang.split(SPLIT_LANG_COUNTRY);
		Locale loc_lang;
		if(lc.length==1) {
			loc_lang= new Locale(lang);
		} else{
			loc_lang=new Locale(lc[0],lc[1]);
		}
		for (Locale cur : localeList) {
			String disc=cur.getDisplayCountry(loc_lang);
			if(disc==null || disc.trim().equals("")){
				continue;
			}
			rl.add(new String[]{cur.getLanguage()+SPLIT_LANG_COUNTRY+cur.getCountry(),
					disc+SPLIT_LANG_COUNTRY+cur.getDisplayLanguage(loc_lang)});
		}
    	return rl;
    }
    @SuppressWarnings("rawtypes")
	private List listEntitys() {		
		org.hibernate.SessionFactory sf = getDao().getSessionFactory();
		Map map = sf.getAllClassMetadata();
		Iterator it = map.entrySet().iterator();  //所有类名
		Vector<String[]> rl = new Vector<String[]>();
		rl.add(new String[]{"无","无"});
		rl.add(new String[]{"全部","全部"});
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String key_en = (String) entry.getKey();
			rl.add(new String[]{key_en,key_en});
		}
		return rl;
	}
    static public String toJSON(Object o){
    	return gson.toJson(o);
    }
    
    public String getJSonTree(String nid){
		List ls = getDao().find("from NSort where nid="+nid);
		HashMap<Integer,Node> nodeMap = new HashMap<Integer,Node>();
		int len_ls=ls.size();
		for(int i=0; i<len_ls; i++){
			NSort ns = (NSort)ls.get(i);
			nodeMap.put(ns.getId(), new Node(ns.getId(),ns.getTitle()));
		}
		Node root = new Node(0,"root");
		for(int i=0; i<len_ls; i++){
			NSort ns = (NSort)ls.get(i);
			Integer pid = ns.getPid();
			int id = ns.getId();
			Node nd = nodeMap.get(id);
			if(pid!=null){
				nodeMap.get(pid).addNode(nd);
			}else{
				root.addNode(nd);
			}
		}
		root.update();
		Gson gson=new GsonBuilder().setPrettyPrinting().create();
		String jstr = gson.toJson(root.getChildren());
    	return jstr;
    }
    public String getOrgTree(String oid){
		List ls = getDao().find("from UOrg");
		HashMap<Integer,NodeSingle> nodeMap = new HashMap<Integer,NodeSingle>();
		int len_ls=ls.size();
		for(int i=0; i<len_ls; i++){
			UOrg ns = (UOrg)ls.get(i);
			if(oid.equals("0"))
				nodeMap.put(ns.getId(), new NodeSingle(ns.getId(),ns.getName()));
			else
				nodeMap.put(ns.getId(), new NodeSingle(ns.getId(),ns.getName(),ns.getId()));
		}
		NodeSingle root = new NodeSingle(0,"root");
		for(int i=0; i<len_ls; i++){
			UOrg ns = (UOrg)ls.get(i);
			Integer pid;
			int id = ns.getId();
			NodeSingle nd = nodeMap.get(id);
			try{
				pid = Integer.parseInt(ns.getPid());
				nodeMap.get(pid).addNode(nd);
			}catch(Exception e){
				root.addNode(nd);
				continue;
			}
			if(pid!=null){
				nodeMap.get(pid).addNode(nd);
			}else{
				root.addNode(nd);
			}
		}
		root.update();
		Gson gson=new GsonBuilder().setPrettyPrinting().create();
		String jstr = gson.toJson(root.getChildren());
    	return jstr;
    }

    /**
     * hql=select userId,userId from UUser'
     * @param hql
     * @return
     */
    private String appendQuery(String hql,String query){
    	if(query==null || query.trim().equals("")) {
			return hql;
		}
    	String rhql;
    	String lhql = hql.toLowerCase();
    	int pos_from = lhql.indexOf("from");
    	int pos_select = lhql.indexOf("select");
    	int pos_where = lhql.indexOf("where");
    	String fldstr = hql.substring(pos_select+7, pos_from);
    	String[] flds=fldstr.split(",");
    	String qstr="";
    	for(int i=0; i<flds.length; i++){
    		if(i==0) {
				qstr = flds[i]+" like "+" '"+query+"%'";
			} else {
				qstr+=" or "+flds[i]+" like "+" '"+query+"%'";
			}
    	}
    	if(pos_where==-1){
    		rhql = hql+" where ("+qstr+")";
    	}else{
    		rhql = hql+" and ("+qstr+")";
    	}
    	return rhql;
    }
    public String getListTree(List ls,String pn_id,String pn_name,String bSingle){
  		Node root = new Node(0,"root");
  		int len_ls=ls.size();
  		for(int i=0; i<len_ls; i++){
  			Object ns = ls.get(i);
  			BeanWrapper bw = new BeanWrapperImpl(ns);
  			Integer id = (Integer)bw.getPropertyValue(pn_id);
  			String name = (String)bw.getPropertyValue(pn_name);
  			Node nd = new Node(id,name);
  			root.addNode(nd);
  			//nodeMap.put(ns.getId(), new Node(ns.getId(),ns.getTitle()));
  		}
  		root.update();
  		GsonBuilder b = new GsonBuilder();		
  		if(bSingle!=null){
  			b.addSerializationExclusionStrategy(new ExclusionStrategy() {

  				@Override
  				public boolean shouldSkipClass(Class<?> arg0) {
  					// TODO Auto-generated method stub
  					return false;
  				}

  				@Override
  				public boolean shouldSkipField(FieldAttributes arg0) {
  					// TODO Auto-generated method stub
  					if(arg0.getName().equals("checked"))
  						return true;
  					return false;
  				}
  	        });
  		}
  		Gson gson=b.setPrettyPrinting().create();
  		String jstr = gson.toJson(root.getChildren());
      	return jstr;
      }
	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String query = request.getParameter("query");
		String nid = request.getParameter("nid");
		String oid = request.getParameter("oid");
		String out;
		if(nid!=null){
			response.getOutputStream().write(getJSonTree(nid).getBytes("utf-8"));		
			return;
		}else if(oid!=null){
			response.getOutputStream().write(getOrgTree(oid).getBytes("utf-8"));		
			return;
		}
		List ls;
		String hql = request.getParameter("hql");
		String status="";
		if(request.getParameter("status")!=null){
			status=request.getParameter("status");
		}
		
		if(hql.equals("LIST_ENTITYS")){
			//对数据库表列表进行缓存
			out = getJSon(hql);
			if(out==null){
				ls = listEntitys();
				out =toJSON(ls);
				putJSon(hql,out);
			}
		}else if(hql.equals("LIST_LANG_")){
			String lang=null;
			try {
			  UUser usr = UMService.getUserBySession(request);
			  lang = usr.getLang();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(lang==null){
				Locale loc=Locale.getDefault();
				lang=loc.getLanguage()+SPLIT_LANG_COUNTRY+loc.getCountry();
			}
			String key =hql+lang;
			out = getJSon(key);
			if(out==null){
				ls = listLang(lang);
				out =toJSON(ls);
				putJSon(key,out);
			}
		}else if(status.equals("tree")){
			    ls = getDao().find(hql);
				out = getListTree(ls,"id","name",request.getParameter("single"));
		}
		else{
			ls = getDao().find(appendQuery(hql,query));
			out =toJSON(ls);
		}
		response.getOutputStream().write(out.getBytes("utf-8"));		
	}
	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request,response);
	}

}
